package com.util.utils;

import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Slf4j
public class Map2Object {

    //Map转化为对象   自动小驼峰映射
    public static <T> T run(Map<String, Object> map, Class<T> clazz) {
        Map<String, Object> newMap = convertKey2Xtf(map);
        try {
            T instance = clazz.getDeclaredConstructor().newInstance();
            Field[] declaredFields = clazz.getDeclaredFields();

            for (Field field : declaredFields) {
                String fieldName = field.getName();
                if (newMap.containsKey(fieldName)) {
                    Object value = newMap.get(fieldName);
                    Object convertedValue = convertValue(value, field.getType());

                    field.setAccessible(true);
                    field.set(instance, convertedValue);
                }
            }
            return instance;

        } catch (InstantiationException | IllegalAccessException |
                 InvocationTargetException | NoSuchMethodException e) {
            throw new RuntimeException("Failed to create instance of " + clazz.getName(), e);
        }
    }

    private static Object convertValue(Object value, Class<?> targetType) {
        if (value == null) {
            return null;
        }

        // 如果已经是目标类型，直接返回
        if (targetType.isInstance(value)) {
            return value;
        }

        // 根据目标类型进行转换
        try {
            if (targetType == String.class) {
                return value.toString();

            } else if (targetType == Integer.class || targetType == int.class) {
                return Integer.parseInt(value.toString());

            } else if (targetType == Long.class || targetType == long.class) {
                return Long.parseLong(value.toString());

            } else if (targetType == Double.class || targetType == double.class) {
                return Double.parseDouble(value.toString());

            } else if (targetType == Float.class || targetType == float.class) {
                return Float.parseFloat(value.toString());

            } else if (targetType == Boolean.class || targetType == boolean.class) {
                return parseBoolean(value);

            } else if (targetType == BigDecimal.class) {
                return new BigDecimal(value.toString());

            } else if (targetType == Date.class) {
                return parseDate(value);

            } else if (targetType == LocalDate.class) {
                return LocalDate.parse(value.toString());

            } else if (targetType == LocalDateTime.class) {
                return LocalDateTime.parse(value.toString(),
                        DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
            }

        } catch (Exception e) {
            throw new RuntimeException("Failed to convert value: " + value +
                    " to type: " + targetType.getName(), e);
        }

        // 无法转换的类型
        throw new IllegalArgumentException("Unsupported target type: " + targetType.getName());
    }

    private static Boolean parseBoolean(Object value) {
        if (value instanceof Boolean) {
            return (Boolean) value;
        }

        String strValue = value.toString().toLowerCase();
        return "true".equals(strValue) || "1".equals(strValue) || "yes".equals(strValue);
    }

    private static Date parseDate(Object value) {
        if (value instanceof Date) {
            return (Date) value;
        }

        if (value instanceof java.sql.Date) {
            return new Date(((java.sql.Date) value).getTime());
        }

        if (value instanceof java.sql.Timestamp) {
            return new Date(((java.sql.Timestamp) value).getTime());
        }

        // 尝试解析字符串格式
        String strValue = value.toString();
        try {
            return new Date(Long.parseLong(strValue)); // 时间戳格式
        } catch (NumberFormatException e) {
            // 不是时间戳，尝试其他格式
            // 这里可以添加更多日期格式解析逻辑
            throw new IllegalArgumentException("Unsupported date format: " + strValue);
        }
    }



    //Map转化为 小驼峰

    public static Map<String, Object> convertKey2Xtf(Map<String, Object> originalMap) {
        Map<String, Object> convertedMap = new HashMap<>();

        for (Map.Entry<String, Object> entry : originalMap.entrySet()) {
            String originalKey = entry.getKey();
            String convertedKey = convertKey(originalKey);
            convertedMap.put(convertedKey, entry.getValue());
        }

        return convertedMap;
    }

    private static String convertKey(String key) {
        // 如果已经是小驼峰格式（首字母小写且不包含下划线），直接返回
        if (key.matches("^[a-z][a-zA-Z0-9]*$") && !key.contains("_")) {
            return key;
        }

        // 转换蛇形命名到驼峰命名
        StringBuilder result = new StringBuilder();
        boolean nextUpper = false;

        for (int i = 0; i < key.length(); i++) {
            char c = key.charAt(i);

            if (c == '_') {
                nextUpper = true;
            } else {
                if (nextUpper) {
                    result.append(Character.toUpperCase(c));
                    nextUpper = false;
                } else {
                    // 第一个字符转为小写
                    if (result.length() == 0) {
                        result.append(Character.toLowerCase(c));
                    } else {
                        result.append(Character.toLowerCase(c));
                    }
                }
            }
        }

        return result.toString();
    }
}
